import {
    DefaultOptons,
    Options,
    TrackerConfig,
    reportTrackerData,
  } from "./core";
  
  import md5 from "md5";
  
  function getExplore() {
    const ua = navigator.userAgent.toLowerCase();
    const matchRegExpArray = [
      { regExp: /rv:([\d.]+)\) like gecko/, browserType: "Internet Explorer" },
      { regExp: /msie ([\d\.]+)/, browserType: "Internet Explorer" },
      { regExp: /(edge|edg)\/([\d\.]+)/, browserType: "Edge" },
      { regExp: /firefox\/([\d\.]+)/, browserType: "Firefox" },
      { regExp: /(?:opera|opr).([\d\.]+)/, browserType: "Opera" },
      { regExp: /chrome\/([\d\.]+)/, browserType: "Chrome" },
      { regExp: /version\/([\d\.]+).*safari/, browserType: "Safari" },
    ];
    let result = "Unknown";
  
    matchRegExpArray.some((item) => {
      const matchResult = ua.match(item.regExp);
      if (matchResult) {
        result = `${matchResult[0]}`;
        return true;
      }
      return false;
    });
  
    return result;
  }
  
  function getCanvasFingerprint() {
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    if (!ctx) {
      return "Unknown";
    }
    var txt = "qu wei zhi";
    ctx.textBaseline = "top";
    ctx.font = "14px 'Arial'";
    ctx.textBaseline = "alphabetic";
    ctx.fillStyle = "#f60";
    ctx.fillRect(125, 1, 62, 20);
    ctx.fillStyle = "#069";
    ctx.fillText(txt, 2, 15);
    ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
    ctx.fillText(txt, 4, 17);
    var dataURI = canvas.toDataURL();
    return md5(dataURI);
  }
  
  // 监听的 DOM　事件
  const MouseEventList: string[] = ["click"];
  
  export class Tracker {
    public data: Options;
    private version: string | undefined;
  
    public constructor(options: Options) {
      this.data = Object.assign(this.initDef(), options);
      this.initBrowser();
      this.installInnerTrack();
    }
  
    private initDef(): DefaultOptons {
      this.version = TrackerConfig.version;
      // 修改 this 指向
      window.history["pushState"] = this.createHistoryEvnent("pushState");
      window.history["replaceState"] = this.createHistoryEvnent("replaceState");
  
      return <DefaultOptons>{
        sdkVersion: this.version,
        historyTracker: false,
        hashTracker: false,
        domTracker: false,
        jsError: false,
      };
    }
  
    // 初始化监听
    private installInnerTrack() {
      if (this.data.historyTracker) {
        this.captureEvents(["pushState"], "history-pv");
        this.captureEvents(["replaceState"], "history-pv");
        this.captureEvents(["popstate"], "history-pv");
      }
      if (this.data.hashTracker) {
        this.captureEvents(["hashchange"], "hash-pv");
      }
      if (this.data.domTracker) {
        this.targetKeyReport();
      }
      if (this.data.jsError) {
        this.errorEvent();
        this.promiseReject();
      }
    }
  
    // 初始化浏览器信息
    private initBrowser() {
      this.data.browser = getExplore();
      this.data.fingerprint = getCanvasFingerprint();
    }
  
    // 监听同步的错误
    private errorEvent() {
      window.addEventListener("error", (e) => {
        this.reportTracker({
          targetKey: "message",
          event: "error",
          message: e.message,
        });
      });
    }
  
    // 监听 promise 的 reject
    private promiseReject() {
      window.addEventListener("unhandledrejection", (event) => {
        event.promise.catch((error) => {
          this.reportTracker({
            targetKey: "reject",
            event: "promise",
            message: error,
          });
        });
      });
    }
  
    // 监听 DOM 事件
    private targetKeyReport() {
      MouseEventList.forEach((event) => {
        window.addEventListener(event, (e) => {
          const target = e.target as HTMLElement;
          const targetValue = target.getAttribute("target-key");
          if (targetValue) {
            this.reportTracker({
              targetKey: targetValue,
              event,
            });
          }
        });
      });
    }
  
    // 监听路由变化
    private captureEvents<T>(
      MouseEventList: string[],
      targetKey: string,
      data?: T
    ) {
      MouseEventList.forEach((event) => {
        window.addEventListener(event, () => {
          this.reportTracker({ event, targetKey, data });
        });
      });
    }
  
    // 重写路由跳转，修改 this 指向
    private createHistoryEvnent = <T extends keyof History>(
      type: T
    ): (() => any) => {
      const origin = history[type];
      return function (this: any) {
        const res = origin.apply(this, arguments);
        var e = new Event(type);
        window.dispatchEvent(e);
        return res;
      };
    };
  
    private reportTracker<T extends reportTrackerData>(data: T) {
      const params = Object.assign(this.data, data, {
        time: new Date().getTime(),
        pageUrl: window.location.href.split("?")[0].replace("/#/", "/"),
      });
      // console.log("发送数据", params);
      let headers = {
        type: "application/x-www-form-urlencoded",
      };
      let blob = new Blob([JSON.stringify(params)], headers);
      navigator.sendBeacon(this.data.requestUrl, blob);
    }
  }
  